package icraf.carbon.gui;

import icraf.carbon.core.AbacusContainer;
import icraf.carbon.core.CostBenefitUnit;
import icraf.carbon.core.OpcostData;
import icraf.carbon.core.Project;
import icraf.carbon.core.Zone;
import icraf.carbon.gui.MenuFactory.MenuProperty;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.JToolBar;
import javax.swing.ListModel;
import javax.swing.RowFilter;
import javax.swing.RowFilter.ComparisonType;
import javax.swing.table.TableRowSorter;

public class OutputEmissionNPVPanel extends JPanel{
	
	public class OptionListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			if (e.getSource().equals(listTypeCB)) {
				int i = listTypeCB.getSelectedIndex();
				if(i == 0) {
					setListType(ZONE_SUMMARY);
					valueTypeCB.setEnabled(true);
				} else if(i == 1) {
					setListType(DETAIL);
					valueTypeCB.setSelectedIndex(1);
					valueTypeCB.setEnabled(false);
				}
			} else if (e.getSource().equals(valueTypeCB)) {
				int i = valueTypeCB.getSelectedIndex();
				if(i == 0) {
					model.setValueType(Zone.NET_EMISSION);
				} else if(i == 1) {
					model.setValueType(Zone.EMISSION);
				} else if(i == 2) {
					model.setValueType(Zone.SEQUESTRATION);
				}
				model.fireTableDataChanged();
			}

		}

	}



	private static final long serialVersionUID = -3066859709096978959L;
	static int DETAIL = 1, ZONE_SUMMARY = 0;
	
	public class ListLUTableModel extends MatrixTableModel {
		private static final long serialVersionUID = 8968868974903218229L;
		
		private int listType = DETAIL;
		
		private CostBenefitUnit costBenefitUnit;
		private String header_detail[] = { 
				MenuProperty.PROJECT_ZONE.getLabel(),
				MenuProperty.PROJECT_LU_FROM.getLabel(),
				MenuProperty.PROJECT_LU_INTO.getLabel(),
				MenuProperty.PROJECT_EMISSION.getLabel(),
				MenuProperty.PROJECT_OPCOST.getLabel(),
				MenuProperty.PROJECT_ZONE_AREA.getLabel(),
				MenuProperty.PROJECT_ZONE_ELIGIBILITY.getLabel()};
		private String header_zone[] = { 
				MenuProperty.PROJECT_ZONE.getLabel(),
				MenuProperty.PROJECT_EMISSION.getLabel(),
				MenuProperty.PROJECT_OPCOST.getLabel(), 
				MenuProperty.PROJECT_ZONE_AREA.getLabel(),
				MenuProperty.PROJECT_ZONE_ELIGIBILITY.getLabel()};
		
		private boolean isAreaScale = false;
		//private ArrayList<OpcostData> luArr;
		private AbacusContainer dataCont;
		private NumberRowHeader tableListModel = new NumberRowHeader(this);
		private boolean isEligibleOnly = false;
		private int valueType = Zone.NET_EMISSION;

		@Override
		public Class<?> getColumnClass(int column) {
			if(getValueAt(0, column) == null) return String.class;
			return getValueAt(0, column).getClass();
		}

		@Override
		public int getColumnCount() {
			if(listType == DETAIL) {
				return header_detail.length;
			} else if(listType == ZONE_SUMMARY) {
				return header_zone.length;
			}
			return 0;
		}

		@Override
		public String getColumnName(int col) {
			if(listType == DETAIL) {
				return header_detail[col];
			} else if(listType == ZONE_SUMMARY) {
				return header_zone[col];
			}
			return "";
		}

		public CostBenefitUnit getCostBenefitUnit() {
			return costBenefitUnit;
		}



		@Override
		public int getRowCount() {
			if (dataCont == null) {
				return 0;
			}
			if(listType == DETAIL) {
				return dataCont.getDataSize(costBenefitUnit);
			} else if(listType == ZONE_SUMMARY) {
				return dataCont.getDataZoneList().size();
			}
			return 0;
		}

		@Override
		public ListModel<Object> getRowHeaderModel() {
			return tableListModel;
		}



		@Override
		public Object getValueAt(int row, int column) {
			if (dataCont == null) {
				return null;
			}
			if(listType == DETAIL) {
				OpcostData d = dataCont.getAbacusData(row, costBenefitUnit);
				switch (column) {
				case 0:
					return d.getZone().getLabel();
				case 1:
					return d.getLandCover1().getLabel();
				case 2:
					return d.getLandCover2().getLabel();
				case 3:
					return d.getEmission()
							* (isAreaScale ? dataCont.getTotalArea() : 1);
				case 4:
					return d.getCost(costBenefitUnit);
				case 5:
					return d.getLandCoverChanges();
				case 6:
					return d.isEligible();
				}
			} else if(listType == ZONE_SUMMARY) {
				Zone z = dataCont.getDataZoneList().get(row);
				switch (column) {
				case 0:
					return z.getLabel();
				case 1:
					return z.getEmissionTotal(valueType, isEligibleOnly)
							* (isAreaScale ? dataCont.getTotalArea() : 1);
				case 2:
					if(valueType == Zone.NET_EMISSION) {
						return null;
					}
					return z.getDeltaNPVTotal(valueType, costBenefitUnit, isEligibleOnly);
				case 3:
					return z.getAreaSize();
				case 4:
					return z.isEligible();
				}
			}
			return null;
			
		}

		public boolean isAreaScale() {
			return isAreaScale;
		}

		@Override
		public boolean isCellEditable(int row, int col) {
			return false;
		}

		public void setAreaScale(boolean isAreaScale) {
			this.isAreaScale = isAreaScale;
			fireTableDataChanged();
		}

		public void setProject(Project project,
				CostBenefitUnit costBenefitUnit) {
			this.dataCont = project;
			this.costBenefitUnit = costBenefitUnit;
//			this.isEligibleOnly  = isEligibleOnly;
			
			fireTableStructureChanged();
			
		}

		public int getListType() {
			return listType;
		}

		public void setListType(int listType) {
			this.listType = listType;
			fireTableStructureChanged();
			tableListModel.fireContentChange(this.getRowCount()-1);
		}

		public int getValueType() {
			return valueType;
		}

		public void setValueType(int valueType) {
			this.valueType = valueType;
		}

	

	}
	
	
	
	private boolean isAreaScale = false;
	private ListLUTableModel model;
	private JComboBox<String> unitCB = new JComboBox<String>();
	private DefaultComboBoxModel<String> unitModelCB = new DefaultComboBoxModel<String>();
	private TableRowSorter<ListLUTableModel> sorter;
	private MatrixPanel matrixPanel;
	private String[] listTypeStr = {MenuProperty.PROJECT_ZONE.getLabel(), MenuProperty.PROJECT_LANDUSE.getLabel()};
	private JComboBox<String> listTypeCB;
	private ActionListener listener = new OptionListener();
	private JComboBox<String> valueTypeCB;
	private String[] valueTypeStr = {"Net "+MenuProperty.PROJECT_EMISSION.getLabel(), MenuProperty.PROJECT_EMISSION.getLabel(), MenuProperty.PROJECT_SEQUESTRATION.getLabel()};
	
	public OutputEmissionNPVPanel() {
		this.setLayout(new BorderLayout());
		model = new ListLUTableModel();
		matrixPanel = new MatrixPanel(model);
		matrixPanel.getTable().setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS);
//		mp.getTable().setAutoCreateRowSorter(true);

		sorter = new TableRowSorter<ListLUTableModel>(model);
		
		List<RowFilter<Object,Object>> filters = new ArrayList<RowFilter<Object,Object>>(2);
		   filters.add(RowFilter.numberFilter(ComparisonType.AFTER, 0d, 3));
		   filters.add(RowFilter.numberFilter(ComparisonType.BEFORE, -0d, 3));
		   sorter.setRowFilter(RowFilter.orFilter(filters));
		 matrixPanel.getTable().setRowSorter(sorter);
		 
		this.add(matrixPanel);

		JLabel l = new JLabel(MenuProperty.PROJECT_EMISSION.getLabel()+" "+ MenuProperty.CHART_AXIS_UNIT.getLabel());
//		emitLabel = new JLabel();

		unitModelCB.addElement(MenuProperty.UNIT_EMISSION_HA.getLabel());
		unitModelCB.addElement(MenuProperty.UNIT_EMISSION.getLabel());
		unitCB.setModel(unitModelCB);
		unitCB.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				setAreaScale(unitCB.getSelectedIndex() == 1);
			}
		});

		listTypeCB = new JComboBox<String>(listTypeStr);
		listTypeCB.setMaximumSize(new Dimension(100, 20));
		listTypeCB.addActionListener(listener);
		
		valueTypeCB = new JComboBox<String>(valueTypeStr);
		valueTypeCB.setMaximumSize(new Dimension(100, 20));
		valueTypeCB.addActionListener(listener);
		
		JToolBar p =  new JToolBar();
		p.setFloatable(false);
		
		p.add(listTypeCB);
		p.addSeparator(new Dimension(20, 20));
		p.add(new JLabel(MenuProperty.PROJECT_FIELDS.getLabel()+":"));
		p.add(valueTypeCB);
		p.addSeparator(new Dimension(20, 20));
		p.add(l);
		p.add(unitCB);
		this.add(p, BorderLayout.NORTH);
	}
	
	 
	private void reset() {
		valueTypeCB.setSelectedIndex(0);
		listTypeCB.setSelectedIndex(1);
		unitCB.setSelectedIndex(0);
	}


	public boolean isAreaScale() {
		return isAreaScale;
	}

	public void setAreaScale(boolean isAreaScale) {
		this.isAreaScale = isAreaScale;
		model.setAreaScale(isAreaScale);
	}

	public void setProject(Project project,
			CostBenefitUnit costBenefitUnit) {
		model.setProject(project, costBenefitUnit);
		reset();
	}
	
	public void setListType(int listType) {
		
		if(listType == ZONE_SUMMARY) {
			matrixPanel.getTable().setRowSorter(null);
		} else {
			matrixPanel.getTable().setRowSorter(sorter);
		}
		model.setListType(listType);
	}
}
